package com.dailyblue.project.smbms.alibaba.user.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dailyblue.project.smbms.alibaba.commons.bean.User;
import com.dailyblue.project.smbms.alibaba.commons.util.JsonResult;
import com.dailyblue.project.smbms.alibaba.commons.util.JwtConfig;
import com.dailyblue.project.smbms.alibaba.commons.util.ResultTool;
import com.dailyblue.project.smbms.alibaba.user.feign.RoleFeign;
import com.dailyblue.project.smbms.alibaba.user.mapper.UserMapper;
import com.dailyblue.project.smbms.alibaba.user.service.UserService;
import com.dailyblue.project.smbms.alibaba.user.util.DateUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private RoleFeign roleFeign;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private DateUtil dateUtil;

    private final static String USER_KEY = "USER_LIST";
    private final static String PAGE_KEY = "PAGE_INFO";

    @Override
    public JsonResult updateUserPassword(int id, String password) {
        return (userMapper.updateUserPassword(id, password) == 1) ? ResultTool.success() : ResultTool.fail();
    }

    @Override
    public JsonResult oldPass(HttpServletRequest request, String oldPass) {
        String token = request.getHeader("token");
        // 这里省略了对token的检验
        Claims claims = JwtConfig.parseJWT(token);
        String id = claims.get("id").toString();

        String op = userMapper.selectById(Integer.parseInt(id)).getUserPassword();
        String op2 = DigestUtils.md5Hex(oldPass);
        if(op.equals(op2)){
            return ResultTool.success(id);
        }
        return ResultTool.fail();
    }

    public JsonResult find(int page) {
        ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        int start = (page - 1) * 5;
        int end = (page * 5) - 1;
        List<String> l = listOperations.range(USER_KEY, start, end);
        log.info("开始分页查询，查询第{}页数据，Redis中的内容是:{}", page, l);
        if (l.size() != 0 && !l.get(0).equals("0")) {
            List<User> list = new ArrayList<>();
            l.forEach(s -> {
                String value = valueOperations.get(s);
                User user = JSONArray.parseObject(value, User.class);
                list.add(user);
            });
            String str = valueOperations.get(PAGE_KEY);
            PageInfo<User> pageInfo = JSONArray.parseObject(str, PageInfo.class);
            /*// 更新数据
            pageInfo.setList(list);
            // 更新页数
            pageInfo.setPageNum(page);
            // 更新上一页
            pageInfo.setPrePage(page - 1 < 1 ? 0 : page - 1);
            // 更新下一页
            pageInfo.setNextPage(page == pageInfo.getPages() ? 0 : page + 1);*/
            pageInfo = updatePage(pageInfo, list, page);
            valueOperations.set(PAGE_KEY, JSONArray.toJSONString(pageInfo));
            return ResultTool.success(pageInfo);
        }
        log.info("Redis中没有数据，开始查询数据库内容");
        PageHelper.startPage(page, 5);
        List<User> list = userMapper.find();
        // 所有的key
        List<String> array = new ArrayList<>();
        list.forEach(u -> {
            int roleId = u.getUserRole();
            JsonResult role = roleFeign.find(roleId);
            log.info("查询角色ID:{},内容:{}", roleId, role);
            u.setRole(role);
            String key = "USER::" + u.getId();
            // 存放用户到Redis中
            valueOperations.setIfAbsent(key, JSONArray.toJSONString(u));
            /*// 存放索引到Redis集合中
            listOperations.rightPush("USER_LIST", key);*/
            //fullList();
            array.add(key);
        });
        PageInfo<User> pageInfo = new PageInfo<>(list);
        valueOperations.set(PAGE_KEY, JSONArray.toJSONString(pageInfo));
        fullList(listOperations, array, start);
        return ResultTool.success(pageInfo);
    }

    @Override
    public JsonResult delete(int id, int page) {
        // 删除数据库中数据
        userMapper.deleteById(id);
        // 更新redis中的缓存
        ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        valueOperations.getAndDelete("USER::" + id);
        listOperations.remove(USER_KEY, 1, "USER::" + id);
        // 对最后一页只有一条数据时的操作
        String value = valueOperations.get(PAGE_KEY);
        PageInfo<User> pageInfo = JSONArray.parseObject(value, PageInfo.class);
        int pages = pageInfo.getPages();
        if (pages == page) {
            long total = pageInfo.getTotal();
            if (total % 5 == 1) {
                page = page == 1 ? 1 : page - 1;
                pageInfo.setPages(pageInfo.getPages() - 1);
            }
        }
        pageInfo.setTotal(pageInfo.getTotal() - 1);
        valueOperations.set(PAGE_KEY, JSONArray.toJSONString(pageInfo));
        // 更新搜索的数据

        // 返回当前数据
        return find(page);
    }

    @Override
    public JsonResult findById(int id) {
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        String value = valueOperations.get("USER::" + id);
        if (value == null || "".equals(value.trim())) {
            return ResultTool.fail();
        }
        User user = JSONArray.parseObject(value, User.class);
        return ResultTool.success(user);
    }

    public JsonResult findByName(String name, int page) {
        PageHelper.startPage(page, 5);
        if ("shinull".equals(name)) {
            name = "";
        }
        List<User> list = userMapper.findByUserName("%" + name + "%");
        list.forEach(u -> {
            int roleId = u.getUserRole();
            JsonResult role = roleFeign.find(roleId);
            log.info("查询角色ID:{},内容:{}", roleId, role);
            u.setRole(role);
        });
        PageInfo<User> pageInfo = new PageInfo<>(list);
        return ResultTool.success(pageInfo);
    }

    @Override
    public JsonResult saveUser(User user, int lastPage, int total) {
        int row = userMapper.insert(user);
        if (row == 0) {
            return ResultTool.fail();
        }
        // 更新redis
        int yushu = total % 5;
        if (yushu != 0) {
            // 向redis中添加一条数据
            ListOperations<String, String> listOperations = stringRedisTemplate.opsForList();
            ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
            PageHelper.startPage(lastPage, 5);
            List<User> list = userMapper.find();
            list.forEach(u -> {
                int roleId = u.getUserRole();
                JsonResult role = roleFeign.find(roleId);
                log.info("查询角色ID:{},内容:{}", roleId, role);
                u.setRole(role);
                String key = "USER::" + u.getId();
                // 存放用户到Redis中
                valueOperations.setIfAbsent(key, JSONArray.toJSONString(u));
            });
            PageInfo<User> pageInfo = new PageInfo<>(list);
            pageInfo = updatePage(pageInfo, list, lastPage);
            valueOperations.set(PAGE_KEY, JSONArray.toJSONString(pageInfo));
            User lastUser = list.get(list.size() - 1);
            log.info("最后一条数据是:{}", lastUser);
            valueOperations.set("USER::" + lastUser.getId(), JSONArray.toJSONString(lastUser));
            listOperations.rightPush(USER_KEY, "USER::" + lastUser.getId());
        }
        return ResultTool.success();
    }

    @Override
    public JsonResult checkPhone(String phone) {

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone", phone);
        long row = userMapper.selectCount(wrapper);
        if (row == 0) {
            return ResultTool.success();
        }

        return ResultTool.fail();
    }

    @Override
    public JsonResult checkCode(String code) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("userCode", code);
        long row = userMapper.selectCount(wrapper);
        if (row == 0) {
            return ResultTool.success();
        }

        return ResultTool.fail();
    }

    @Override
    public JsonResult findUserById(int id) {
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        String str = valueOperations.get("USER::" + id);
        User user;
        if (str == null) {
            user = userMapper.selectById(id);
            user.setRole(roleFeign.find(user.getUserRole()));
            valueOperations.set("USER::" + id, JSONArray.toJSONString(user));
            return ResultTool.success(user);
        }
        user = JSONArray.parseObject(str, User.class);
        return ResultTool.success(user);
    }

    @Override
    public JsonResult updateUser(User user) {
        int row = userMapper.updateById(user);
        if (row == 0) {
            return ResultTool.fail();
        }
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        String str = valueOperations.get("USER::" + user.getId());
        User user1 = JSONArray.parseObject(str, User.class);
        user1.setUserName(user.getUserName());
        user1.setPhone(user.getPhone());
        user1.setGender(user.getGender());
        user1.setBirthday(user.getBirthday());
        user1.setAddress(user.getAddress());
        user1.setUserAge(dateUtil.getAge(user1.getBirthday()));
        valueOperations.set("USER::" + user1.getId(), JSONArray.toJSONString(user1));
        return ResultTool.success();
    }

    private PageInfo<User> updatePage(PageInfo<User> pageInfo, List<User> list, int page) {
        // 更新数据
        pageInfo.setList(list);
        // 更新页数
        pageInfo.setPageNum(page);
        // 更新上一页
        pageInfo.setPrePage(page - 1 < 1 ? 0 : page - 1);
        // 更新下一页
        pageInfo.setNextPage(page == pageInfo.getPages() ? 0 : page + 1);
        return pageInfo;
    }

    /*
            list:Redis中的集合
            keys:我要存放的内容
            start:把这些keys存放到list中的哪个位置
         */
    private void fullList(ListOperations<String, String> list, List<String> keys, int start) {
        log.info("开始存放集合");
        long size = list.size(USER_KEY);
        log.info("集合的长度是：{}", size);
        // 填充0以占据位置
        if (size != start) {
            // 填充null
            long fullSize = start - size;
            log.info("填充{}个0,", fullSize);
            for (int i = 0; i < fullSize; i++) {
                list.rightPush(USER_KEY, "0");
            }
        }
        List<String> beforeData = list.range(USER_KEY, start, start + keys.size() - 1);
        log.info("原有的数据:{}", beforeData);
        if (beforeData.size() == 0) {
            keys.forEach(e -> {
                list.rightPush(USER_KEY, e);
            });
        } else {
            log.info("开始从{}修改0的内容,一共：{}个", start, start + keys.size());
            for (int i = 0; i < beforeData.size(); i++) {
                list.set(USER_KEY, start + i, keys.get(i));
            }

        }
    }
}
